package com.lml.basicscodelab

import android.content.res.Configuration
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandLess
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.lml.basicscodelab.ui.theme.ComposeTutorialTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeTutorialTheme {
                MyApp(modifier = Modifier.fillMaxSize())
            }
        }
    }
}

@Composable
private fun MyApp(modifier: Modifier = Modifier) {

    var shouldShowOnboarding by rememberSaveable { mutableStateOf(true) }

    Surface(modifier) {
        if (shouldShowOnboarding) {
            OnboardingScreen(onContinueClicked = { shouldShowOnboarding = false })
        } else {
            Greetings()
        }
    }
}

@Composable
private fun OnboardingScreen(onContinueClicked: () -> Unit, modifier: Modifier = Modifier) {

    Column(
        // fillMaxSize可以理解为Android View中的match parent
        modifier = Modifier.fillMaxSize(),
        // 设置垂直居中排列
        verticalArrangement = Arrangement.Center,
        // 设置水平居中排列
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "Welcome to the Basics Codelab!")
        Button(
            modifier = Modifier.padding(vertical = 24.dp),
            onClick = onContinueClicked
        ) {
            Text(text = "Continue")
        }
    }
}

@Composable
private fun Greetings(
    modifier: Modifier = Modifier,
    /**
     * List(1000): 创建一个包含 1000 个元素的列表。
     * { "$it" }: 这是一个 lambda 表达式，它定义了列表中每个元素的值。$it 表示 lambda 表达式的参数，即元素的索引，然后将其转换为字符串。
     * {"$it"}使用了 Kotlin 中的字符串模板语法糖，等价于{index -> "$index"}
     * 因为在调用Greeting进行展示时是Text文本，所以这里将其转换成了字符串格式
     * 其实也可以是{index -> index.toString()}，但这就是Java中的写法了，虽然也可以，不过既然kotlin提供了字符串模版语法糖，并且Compose是使用kotlin语言的，当然直接"$index"更好
     */
    names: List<String> = List(1000) { "$it" }
) {
    // 需要添加如下包
    // import androidx.compose.foundation.lazy.LazyColumn
    // import androidx.compose.foundation.lazy.items
    LazyColumn(modifier = modifier.padding(vertical = 4.dp)) {
        items(items = names) { name -> Greeting2(name = name) }
    }
}

@Composable
private fun Greeting2(name: String, modifier: Modifier = Modifier) {
    Card(
        colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primary),
        modifier = modifier.padding(vertical = 4.dp, horizontal = 8.dp)
    ) {
        CardContent(name)
    }
}

@Composable
private fun CardContent(name: String) {

    var expanded by rememberSaveable {
        mutableStateOf(false)
    }

    Row(
        modifier = Modifier
            .padding(12.dp)
            // animateContentSize 是 Jetpack Compose 中的一个修饰符（Modifier），用于在动画过渡期间自动调整包含的内容的大小。
            // 它是为了在内容发生变化时，通过动画平滑过渡大小的一个方便工具。使用这个修改符后就不需要在下面的内容修饰中符添加coerceAtLeast。
            .animateContentSize(
                animationSpec = spring(
                    dampingRatio = Spring.DampingRatioMediumBouncy,
                    stiffness = Spring.StiffnessLow
                )
            )
    ) {
        Column(
            modifier = Modifier
                .weight(1f)
                .padding(12.dp)
        ) {
            Text(text = "Hello,")
            Text(
                text = name, style = MaterialTheme.typography.headlineMedium.copy(
                    fontWeight = FontWeight.ExtraBold
                )
            )
            if (expanded) {
                Text(
                    text = ("Composem ipsum color sit lazy, " +
                            "padding theme elit, sed do bouncy. ").repeat(4),
                )
            }
        }
        IconButton(onClick = { expanded = !expanded }) {
            // Icon 用于显示一个矢量图标。你可以指定图标的图案、颜色、大小等属性。通常，你会为 Icon 提供一个 imageVector 或 bitmap，以指定要显示的图标。
            // imageVector矢量图：不会失真，文件相对小，用于图标。
            // bitmap位图：会失真，文件相对大，用于照片。
            Icon(
                // 用于指定图标的图案。可以使用 Icons.Default 中的默认图标，也可以使用自定义的图标。
                imageVector = if (expanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore,
                // 提供一个内容描述，以帮助辅助技术用户理解图标的含义。
                contentDescription = if (expanded) {
                    stringResource(R.string.show_less)
                } else {
                    stringResource(R.string.show_more)
                },
                // tint: 指定图标的颜色。
                tint = Color.Magenta
            )
        }
    }
}

@Composable
private fun Greeting(name: String) {

    // 使用属性委托时会报错，需要添加以下这两个包
    // import androidx.compose.runtime.getValue
    // import androidx.compose.runtime.setValue
    // var shouldShowOnboarding by remember { mutableStateOf(true) }
    var expanded by remember { mutableStateOf(false) }

    // extraPadding: 这是一个由 animateDpAsState 创建的动画状态。这个状态将在动画过程中从一个值过渡到另一个值。
    // (if (expanded) 48.dp else 0.dp): 这是动画状态的起始值和结束值。如果 expanded 为 true，则起始值是 48.dp，否则是 0.dp。
    // 这表示 extraPadding 的值将在动画过程中从 48.dp 过渡到 0.dp 或从 0.dp 过渡到 48.dp，具体取决于 expanded 的值。
    // animationSpec: 这是定义动画的规格，使用 spring 函数创建了一个弹簧动画。在这个例子中，使用了 Medium Bouncy 阻尼比和 Low 刚度，
    // 这会产生一个有弹簧效果的动画。
    val extraPadding by animateDpAsState(
        if (expanded) 48.dp else 0.dp, label = "添加一个label",
        animationSpec = spring(
            // dampingRatio 阻尼比
            // stiffness 刚度
            dampingRatio = Spring.DampingRatioMediumBouncy,
            stiffness = Spring.StiffnessLow
        )
    )

    Surface(
        color = MaterialTheme.colorScheme.primary,
        modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
    ) {
        /**
         * 在Jetpack Compose中，Modifier.padding 函数接受一个 Dp（密度无关像素）类型的参数，而不是直接使用像素值。
         * 这是因为在不同的屏幕密度下，使用密度无关像素更具灵活性，可以确保在不同设备上获得一致的外观。
         */
        Row(modifier = Modifier.padding(24.dp)) {
            Column(
                modifier = Modifier
                    .weight(1f)
                    // coerceAtLeast 是 Kotlin 标准库中的一个函数，用于确保一个值不小于指定的下限。如果当前值小于指定的下限，coerceAtLeast 将返回下限值，否则返回原始值。
                    .padding(bottom = extraPadding.coerceAtLeast(0.dp))
            ) {
                Text(text = "Hello,")
                Text(
                    text = name, style = MaterialTheme.typography.headlineMedium.copy(
                        fontWeight = FontWeight.ExtraBold
                    )
                )
            }
            ElevatedButton(onClick = {
                expanded = !expanded
            }) {
                Text(if (expanded) "show less" else "show more")
            }
        }
    }
}

@Preview(
    showBackground = true,
    widthDp = 320,
    uiMode = Configuration.UI_MODE_NIGHT_YES,
    name = "GreetingPreviewDark"
)
@Preview(showBackground = true, widthDp = 320)
@Composable
private fun GreetingPreview() {
    ComposeTutorialTheme {
        Greetings()
    }
}

@Preview(showBackground = true, widthDp = 320, heightDp = 320)
@Composable
fun OnBoardingPreview() {
    ComposeTutorialTheme {
        OnboardingScreen(onContinueClicked = {})
    }
}

@Preview
@Composable
private fun MyAppPreview() {
    ComposeTutorialTheme {
        MyApp(modifier = Modifier.fillMaxSize())
    }
}